package com.nuoniu.sibanyun.service.po.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nuoniu.sibanyun.common.exception.NuoNiuException;
import com.nuoniu.sibanyun.common.lang.StringUtils;
import com.nuoniu.sibanyun.common.result.HttpResult;
import com.nuoniu.sibanyun.entity.bo.*;
import com.nuoniu.sibanyun.entity.erp.ErpNumberSet;
import com.nuoniu.sibanyun.entity.po.VPurchaseArrivalDetail;
import com.nuoniu.sibanyun.entity.po.VPurchaseArrivalMain;
import com.nuoniu.sibanyun.entity.po.VPurchaseInvoiceDetail;
import com.nuoniu.sibanyun.entity.po.VPurchaseInvoiceMain;
import com.nuoniu.sibanyun.mapper.erp.ErpNumberSetMapper;
import com.nuoniu.sibanyun.mapper.po.VPurchaseArrivalMainMapper;
import com.nuoniu.sibanyun.service.crm.ICrmGoodsService;
import com.nuoniu.sibanyun.service.erp.IErpAccountService;
import com.nuoniu.sibanyun.service.erp.IErpNumberSetService;
import com.nuoniu.sibanyun.service.erp.IErpVoucherDesignService;
import com.nuoniu.sibanyun.service.po.IVPurchaseArrivalDetailService;
import com.nuoniu.sibanyun.service.po.IVPurchaseArrivalMainService;
import com.nuoniu.sibanyun.service.po.IVPurchaseInvoiceMainService;
import com.nuoniu.sibanyun.service.utils.ErpUtils;
import com.nuoniu.sibanyun.userThread.UserInfo;
import com.nuoniu.sibanyun.userThread.UserThreadLocal;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 采购到货单主表 服务实现类
 * @author 小啊刚
 * @since 2020-11-19
 */
@Service
public class VPurchaseArrivalMainServiceImpl extends ServiceImpl<VPurchaseArrivalMainMapper, VPurchaseArrivalMain> implements IVPurchaseArrivalMainService {

    @Autowired
    private IErpNumberSetService numberSetService;
    @Autowired
    private ErpNumberSetMapper numberSetMapper;
    @Autowired
    private IVPurchaseArrivalDetailService arrivalDetailService;
    @Autowired
    private IErpAccountService erpAccountService;
    @Autowired
    private ICrmGoodsService crmGoodsService;


    @Autowired
    private IErpVoucherDesignService erpVoucherDesignService;

    @Autowired
    private IVPurchaseInvoiceMainService invoiceMainService;

    @Override
    public String getCode(Integer companyId) {
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        ErpNumberSet numberSet = numberSetMapper.getByCode("PuArrival", companyId, currentAccountId);
        String dateStr = numberSet.getMedian() == 1 ? "%Y-%m-%d" : "%Y-%m";
        String code = baseMapper.getNewestCode(companyId, dateStr,"PuArrival");
        return numberSetService.getCode(numberSet, code);
    }



    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveOrder(VPurchaseArrivalMain purchaseArrivalMain) {
        Boolean isNewMain = false;
        List<VPurchaseArrivalDetail> orderDetailList = purchaseArrivalMain.getOrderDetailList();
        if(null == orderDetailList)throw new NuoNiuException("单据明细不能为空");
        Long mainId = purchaseArrivalMain.getId();
        UserInfo userInfo = UserThreadLocal.get();
        purchaseArrivalMain.setCompanyId(userInfo.getCompanyId());
        VPurchaseArrivalMain oldVPurchaseArrivalMain = null;
        Integer businessType = purchaseArrivalMain.getBusinessType();
//        if(null != businessType && ( 97 == businessType || 99 == businessType) && orderDetailList.stream().anyMatch(f->f.getBaseQuantity().compareTo(BigDecimal.ZERO) > 0)){
//            throw new NuoNiuException("单据明细错误：退货业务的明细数量不能为正数");
//        }
        if(mainId == null) {
            isNewMain = true;
            String code = getCode(userInfo.getCompanyId());
            if(code == null) {
                throw new NuoNiuException("到货单编号已上限");
            }
            boolean isHaveId = orderDetailList.stream().anyMatch(f -> null != f.getId());
            if(isHaveId)throw new NuoNiuException("单据明细错误：不能新增已经存在的明细记录");
            purchaseArrivalMain.setDataSource("PuArrival");
            purchaseArrivalMain.setAccountId(erpAccountService.getCurrentAccountId());
            purchaseArrivalMain.setVoucherState(-1);
            purchaseArrivalMain.setVoucherCode(code);
            purchaseArrivalMain.setCompanyId(userInfo.getCompanyId());
            purchaseArrivalMain.setCreateUserId(userInfo.getUserId());
            purchaseArrivalMain.setClosedUserName(userInfo.getRealName());
            purchaseArrivalMain.setCumExecuteQuantity(new BigDecimal(0.0));
            purchaseArrivalMain.setCumRetQuantity(new BigDecimal(0.0));
            if (null == purchaseArrivalMain.getBusinessType()){
                purchaseArrivalMain.setBusinessType(0);
            }
        }else {
            //校验详情（详情不能有其他单据的明细ID）
            boolean isHaveErrorId = orderDetailList.stream().anyMatch(f -> null != f.getOrderId() && !mainId.toString().equals(f.getOrderId().toString()));
            if(isHaveErrorId)throw new NuoNiuException("单据明细错误：不能修改其他单据的明细记录");
            purchaseArrivalMain.setUpdateUserId(userInfo.getUserId());
            purchaseArrivalMain.setUpdateDate(LocalDateTime.now());

            oldVPurchaseArrivalMain = getById(mainId);
            /**************  修改权限 *******************/
            if(!crmGoodsService.isHaveOperationRight(oldVPurchaseArrivalMain.getCreateUserId().longValue())){
                throw new NuoNiuException("你没有权限操作该记录");
            }
            Integer voucherState = oldVPurchaseArrivalMain.getVoucherState();
            if(null != voucherState && voucherState > 0){
                throw new NuoNiuException("已审核,不能修改");
            }
            purchaseArrivalMain.setAccountId(oldVPurchaseArrivalMain.getAccountId());
            purchaseArrivalMain.setSourceVoucherCode(oldVPurchaseArrivalMain.getSourceVoucherCode());
            purchaseArrivalMain.setSourceVoucherId(oldVPurchaseArrivalMain.getSourceVoucherId());
            purchaseArrivalMain.setSourceVoucherType(oldVPurchaseArrivalMain.getSourceVoucherType());
            purchaseArrivalMain.setSourceVoucherDate(oldVPurchaseArrivalMain.getSourceVoucherDate());
            //不可更新字段
            purchaseArrivalMain.setVoucherCode(null);
        }
        // 校验 明细数量
//        if(null != businessType && ( 99 == businessType || 97  == businessType )){
//            boolean isOk = purchaseArrivalMain.getOrderDetailList().stream().anyMatch(f -> null == f.getBaseQuantity() || !(f.getBaseQuantity().compareTo(BigDecimal.ZERO) < 0));
//            if(isOk)throw new NuoNiuException("明细数量必须小于0");
//        }else{
//            boolean isOk = purchaseArrivalMain.getOrderDetailList().stream().anyMatch(f -> null == f.getBaseQuantity() || !(f.getBaseQuantity().compareTo(BigDecimal.ZERO) > 0));
//            if(isOk)throw new NuoNiuException("明细数量必须大于0");
//        }
        boolean isOk = purchaseArrivalMain.getOrderDetailList().stream().anyMatch(f -> null == f.getBaseQuantity() || !(f.getBaseQuantity().compareTo(BigDecimal.ZERO) > 0));
        if(isOk)throw new NuoNiuException("明细数量必须大于0");
        //计算 明细物料 总数
        BigDecimal totalQuantity =  purchaseArrivalMain.getOrderDetailList().stream().map(VPurchaseArrivalDetail::getBaseQuantity).reduce(BigDecimal.ZERO,BigDecimal::add);
        purchaseArrivalMain.setTotalQuantity(totalQuantity.abs());
        Boolean result = this.saveOrUpdate(purchaseArrivalMain);
        if(result) {
            List<Long> detailIds = new ArrayList<>();
            orderDetailList.forEach(p -> {
                p.setCompanyId(userInfo.getCompanyId());
                p.setAccountId(purchaseArrivalMain.getAccountId());
                p.setOrderId(purchaseArrivalMain.getId().intValue());
                p.setSourceVoucherCode(purchaseArrivalMain.getSourceVoucherCode());
                p.setSourceVoucherType(purchaseArrivalMain.getSourceVoucherType());
                p.setSourceVoucherDate(purchaseArrivalMain.getSourceVoucherDate());
                p.setSourceVoucherId(purchaseArrivalMain.getSourceVoucherId());
                if(p.getId() != null) {
                    detailIds.add(p.getId());
                }
            });
            boolean isDealDelete = false;
            if (null != mainId){
                //删除明细
                QueryWrapper<VPurchaseArrivalDetail> wrapper = new QueryWrapper();
                wrapper.eq("order_id", mainId);
                if(detailIds != null && detailIds.size() > 0) {
                    wrapper.notIn("id", detailIds);
                }
                isDealDelete = arrivalDetailService.remove(wrapper);
            }
            //保存单据明细表
            arrivalDetailService.saveOrUpdateBatch(orderDetailList);
            // *** 如果 来源订单不为空,校验
            if(null != purchaseArrivalMain.getSourceVoucherId()){
                if(isDealDelete)throw new NuoNiuException("有来源的单据不能删除明细");
                if(!"PurchaseOrder".equals(purchaseArrivalMain.getSourceVoucherType()) && !"PuArrival".equals(purchaseArrivalMain.getSourceVoucherType()))throw new NuoNiuException("采购到货单的来源单，只能是采购订单或者采购到货单");
                if(null != businessType && (99 == purchaseArrivalMain.getBusinessType() || 97 == purchaseArrivalMain.getBusinessType())&& !"PuArrival".equals(purchaseArrivalMain.getSourceVoucherType()))throw new NuoNiuException("退货流程的采购到货单的来源单，只能是采购到货单");
                if(null != businessType &&  (99 != purchaseArrivalMain.getBusinessType()  && 97 != purchaseArrivalMain.getBusinessType())&& !"PurchaseOrder".equals(purchaseArrivalMain.getSourceVoucherType()))throw new NuoNiuException("非退货流程的采购到货单的来源单，只能是采购订单");

                if(purchaseArrivalMain.getBusinessType().equals("PurchaseOrder")) {

                }

                //1.是否是退货单且是普通退货流程
                if(null != businessType && 99 == purchaseArrivalMain.getBusinessType()){
                    VoucherMainRetBo voucherMainRetBo = new VoucherMainRetBo();
                    BeanUtils.copyProperties(purchaseArrivalMain,voucherMainRetBo);
                    List<VoucherDetailRetBo> voucherDetailRetBos = new ArrayList<>();
                    orderDetailList.forEach(detail->{
                        VoucherDetailRetBo voucherDetailRetBo = new VoucherDetailRetBo();
                        voucherDetailRetBos.add(voucherDetailRetBo);
                        BeanUtils.copyProperties(detail,voucherDetailRetBo);
                    });

                    VoucherSearchBo voucherSearchBo = new VoucherSearchBo();
                    voucherSearchBo.setSourceVoucherId(purchaseArrivalMain.getSourceVoucherId());
                    voucherSearchBo.setSourceVoucherType(purchaseArrivalMain.getSourceVoucherType());
                    voucherSearchBo.setVoucherId(purchaseArrivalMain.getId().intValue());
                    voucherSearchBo.setVoucherType("PuArrival");
                    //如果 是从 “退货冲抵” 到 “普通退货”，则先删除 冲抵执行情况，再做普通退货业务
                    if(null != oldVPurchaseArrivalMain &&  null != oldVPurchaseArrivalMain.getBusinessType() &&  oldVPurchaseArrivalMain.getBusinessType() == 97){
                        VoucherMainBo voucherMainBo = new VoucherMainBo();
                        BeanUtils.copyProperties(purchaseArrivalMain,voucherMainBo);
                        voucherMainBo.setBusinessType(97);   //对97做删除操作
                        List<VoucherDetailBo> voucherDetailBos = new ArrayList<>();
                        orderDetailList.forEach(detail->{
                            VoucherDetailBo voucherDetailBo = new VoucherDetailBo();
                            voucherDetailBos.add(voucherDetailBo);
                            BeanUtils.copyProperties(detail,voucherDetailBo);
                        });
//                        /************ 查询当前单据 是否有删除 明细单据(新增删除 明细记录) -- START -- ************/
//                        if(!isDealDelete){
//                            removeDetails.forEach(detail->{
//                                VoucherDetailBo voucherDetailBo = new VoucherDetailBo();
//                                voucherDetailBos.add(voucherDetailBo);
//                                BeanUtils.copyProperties(detail,voucherDetailBo);
//                            });
//                            isDealDelete = true;
//                        }
//                        /************ 查询当前单据 是否有删除 明细单据 -- END -- ************/
                        voucherSearchBo.setCalculateType(2);
                        erpVoucherDesignService.calculateSourceVoucher(voucherMainBo,voucherDetailBos,voucherSearchBo);
                    }
//                    /************ 查询当前单据 是否有删除 明细单据（重新组装 明细记录） -- START -- ************/
//                    if(!isDealDelete){
//                        List<VoucherDetailRetBo> deleteVoucherDetailRetBos = new ArrayList<>();
//                        removeDetails.forEach(detail->{
//                            VoucherDetailRetBo voucherDetailRetBo = new VoucherDetailRetBo();
//                            deleteVoucherDetailRetBos.add(voucherDetailRetBo);
//                            BeanUtils.copyProperties(detail,voucherDetailRetBo);
//                        });
//                        voucherSearchBo.setCalculateType(2);
//                        erpVoucherDesignService.calculateRetQuantity(voucherMainRetBo,deleteVoucherDetailRetBos,voucherSearchBo);
//                    }
//                    /************ 查询当前单据 是否有删除 明细单据 -- END -- ************/
                    voucherSearchBo.setCalculateType(1);

                    erpVoucherDesignService.calculateRetQuantity(voucherMainRetBo,voucherDetailRetBos,voucherSearchBo);
                }else{

                    VoucherMainBo voucherMainBo = new VoucherMainBo();
                    BeanUtils.copyProperties(purchaseArrivalMain,voucherMainBo);
                    voucherMainBo.setIsNewMain(isNewMain);
                    List<VoucherDetailBo> voucherDetailBos = new ArrayList<>();
                    orderDetailList.forEach(detail->{
                        VoucherDetailBo voucherDetailBo = new VoucherDetailBo();
                        voucherDetailBos.add(voucherDetailBo);
                        BeanUtils.copyProperties(detail,voucherDetailBo);
                    });
                    VoucherSearchBo voucherSearchBo = new VoucherSearchBo();
                    voucherSearchBo.setSourceVoucherId(purchaseArrivalMain.getSourceVoucherId());
                    voucherSearchBo.setSourceVoucherType(purchaseArrivalMain.getSourceVoucherType());
                    voucherSearchBo.setVoucherId(purchaseArrivalMain.getId().intValue());
                    voucherSearchBo.setVoucherType("PuArrival");


                    //如果 是从 “普通退货” 到 “退货冲抵”，则先删除 普通退货 执行情况，再做普通退货业务
                    if(null != businessType && 97 == purchaseArrivalMain.getBusinessType() && null != oldVPurchaseArrivalMain && null != oldVPurchaseArrivalMain.getBusinessType()  &&  oldVPurchaseArrivalMain.getBusinessType() == 99){
                        VoucherMainRetBo voucherMainRetBo = new VoucherMainRetBo();
                        BeanUtils.copyProperties(purchaseArrivalMain,voucherMainRetBo);
                        voucherMainBo.setBusinessType(99);   //对99做删除操作
                        List<VoucherDetailRetBo> voucherDetailRetBos = new ArrayList<>();
                        orderDetailList.forEach(detail->{
                            VoucherDetailRetBo voucherDetailRetBo = new VoucherDetailRetBo();
                            voucherDetailRetBos.add(voucherDetailRetBo);
                            BeanUtils.copyProperties(detail,voucherDetailRetBo);
                        });
//                        /************ 查询当前单据 是否有删除 明细单据(新增删除 明细记录) -- START -- ************/
//                        if(!isDealDelete){
//                            removeDetails.forEach(detail->{
//                                VoucherDetailRetBo voucherDetailRetBo = new VoucherDetailRetBo();
//                                voucherDetailRetBos.add(voucherDetailRetBo);
//                                BeanUtils.copyProperties(detail,voucherDetailRetBo);
//                            });
//                            isDealDelete = true;
//                        }
//                        /************ 查询当前单据 是否有删除 明细单据 -- END -- ************/
                        voucherSearchBo.setCalculateType(2);
                        erpVoucherDesignService.calculateRetQuantity(voucherMainRetBo,voucherDetailRetBos,voucherSearchBo);
                    }
//                    /************ 查询当前单据 是否有删除 明细单据（重新组装 明细记录） -- START -- ************/
//                    if(!isDealDelete){
//                        List<VoucherDetailBo> deleteVoucherDetailBos = new ArrayList<>();
//                        orderDetailList.forEach(detail->{
//                            VoucherDetailBo voucherDetailBo = new VoucherDetailBo();
//                            deleteVoucherDetailBos.add(voucherDetailBo);
//                            BeanUtils.copyProperties(detail,voucherDetailBo);
//                        });
//                        voucherSearchBo.setCalculateType(2);
//                        erpVoucherDesignService.calculateSourceVoucher(voucherMainBo,deleteVoucherDetailBos,voucherSearchBo);
//                    }
//                    /************ 查询当前单据 是否有删除 明细单据 -- END -- ************/
                    voucherSearchBo.setCalculateType(1);
                    erpVoucherDesignService.calculateSourceVoucher(voucherMainBo,voucherDetailBos,voucherSearchBo);
                }

            }
        }
    }

    @Override
    public List<VPurchaseArrivalMain> getBySourceCode(String sourceVoucherCode) {
        return baseMapper.getBySourceCode(sourceVoucherCode, UserThreadLocal.get().getCompanyId());
    }

    @Override
    public void submit(Long id, Integer status) {
        if(null == id || null == status || (null != status && (status > 0 || status < -1 )))throw new NuoNiuException("参数错误");
        UserInfo userInfo = UserThreadLocal.get();
        VPurchaseArrivalMain purchaseArrivalMain = this.getById(id);
        if( null == purchaseArrivalMain)throw new NuoNiuException("记录不存在");
        //校验状态
        Integer voucherState = purchaseArrivalMain.getVoucherState();
        if(status == 0){
            if (voucherState > -1)throw new NuoNiuException("该单据已经提交");
        }else if(status == -1){
            if (voucherState > 0)throw new NuoNiuException("该单据已经审核,请先弃审");
        }
        //提交
        purchaseArrivalMain.setVoucherState(status);
        purchaseArrivalMain.setSubmitDate(LocalDateTime.now());
        purchaseArrivalMain.setSubmitUserId(userInfo.getUserId());
        purchaseArrivalMain.setSubmitUserName(userInfo.getRealName());
        this.updateById(purchaseArrivalMain);
    }

    @Override
    public void examine(Long id, Integer status) {
        UserInfo userInfo = UserThreadLocal.get();
        VPurchaseArrivalMain purchaseArrivalMain = this.getById(id);
        if(purchaseArrivalMain == null) {
            throw new NuoNiuException("单据不存在");
        }
        Integer voucherState = purchaseArrivalMain.getVoucherState();
        BigDecimal cumExecuteQuantity = purchaseArrivalMain.getCumExecuteQuantity();
        /** 统一校验 审核状态*/
        ErpUtils.checkExamineStatus(voucherState,status,cumExecuteQuantity);
        purchaseArrivalMain.setVoucherState(status);
        purchaseArrivalMain.setReviewerUserId(userInfo.getUserId());
        purchaseArrivalMain.setReviewerUserName(userInfo.getRealName());
        purchaseArrivalMain.setReviewerDate(LocalDateTime.now());
        this.updateById(purchaseArrivalMain);

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteById(Long id) {
        UserInfo userInfo = UserThreadLocal.get();
        VPurchaseArrivalMain purchaseArrivalMain = getById(id);
        if(purchaseArrivalMain == null) {
           throw new NuoNiuException("此单据不存在");
        }
        /**************  修改权限 *******************/
        if(!crmGoodsService.isHaveOperationRight(purchaseArrivalMain.getCreateUserId().longValue())){
            throw new NuoNiuException("你没有权限操作该记录");
        }

        //如果 来源订单 不为空
        if(null != purchaseArrivalMain.getSourceVoucherId()){
            // 查询 当前单据明细
            List<VPurchaseArrivalDetail> orderDetails = arrivalDetailService.getOrderDetails(id);
            //1.是否是退货单且是普通退货流程
            if(null != purchaseArrivalMain.getBusinessType() && 99 == purchaseArrivalMain.getBusinessType() ){
                VoucherMainRetBo voucherMainRetBo = new VoucherMainRetBo();
                BeanUtils.copyProperties(purchaseArrivalMain,voucherMainRetBo);
                List<VoucherDetailRetBo> voucherDetailRetBos = new ArrayList<>();
                orderDetails.forEach(detail->{
                    VoucherDetailRetBo voucherDetailRetBo = new VoucherDetailRetBo();
                    voucherDetailRetBos.add(voucherDetailRetBo);
                    BeanUtils.copyProperties(detail,voucherDetailRetBo);
                });
                VoucherSearchBo voucherSearchBo = new VoucherSearchBo();
                voucherSearchBo.setCalculateType(2);
                voucherSearchBo.setSourceVoucherId(purchaseArrivalMain.getSourceVoucherId());
                voucherSearchBo.setSourceVoucherType(purchaseArrivalMain.getSourceVoucherType());
                voucherSearchBo.setVoucherId(purchaseArrivalMain.getId().intValue());
                voucherSearchBo.setVoucherType("PuArrival");
                erpVoucherDesignService.calculateRetQuantity(voucherMainRetBo,voucherDetailRetBos,voucherSearchBo);
            }else{

                VoucherMainBo voucherMainBo = new VoucherMainBo();
                BeanUtils.copyProperties(purchaseArrivalMain,voucherMainBo);
                List<VoucherDetailBo> voucherDetailBos = new ArrayList<>();
                orderDetails.forEach(detail->{
                    VoucherDetailBo voucherDetailBo = new VoucherDetailBo();
                    voucherDetailBos.add(voucherDetailBo);
                    BeanUtils.copyProperties(detail,voucherDetailBo);
                });
                VoucherSearchBo voucherSearchBo = new VoucherSearchBo();
                voucherSearchBo.setCalculateType(2);
                voucherSearchBo.setSourceVoucherId(purchaseArrivalMain.getSourceVoucherId());
                voucherSearchBo.setSourceVoucherType(purchaseArrivalMain.getSourceVoucherType());
                voucherSearchBo.setVoucherId(purchaseArrivalMain.getId().intValue());
                voucherSearchBo.setVoucherType("PuArrival");
                erpVoucherDesignService.calculateSourceVoucher(voucherMainBo,voucherDetailBos,voucherSearchBo);
            }
        }
        removeById(id);
        arrivalDetailService.removeByOrderId(id);
    }




    @Override
    public String getCodeForDelegate() {
        UserInfo userInfo = UserThreadLocal.get();
        Integer companyId = userInfo.getCompanyId();
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        ErpNumberSet numberSet = numberSetMapper.getByCode("DelegateArrival", companyId, currentAccountId);
        String dateStr = numberSet.getMedian() == 1 ? "%Y-%m-%d" : "%Y-%m";
        String code = baseMapper.getNewestCode(companyId, dateStr,"DelegateArrival");
        return numberSetService.getCode(numberSet, code);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveOrderForDelegate(VPurchaseArrivalMain purchaseArrivalMain) {
            Boolean isNewMain = false;
            List<VPurchaseArrivalDetail> orderDetailList = purchaseArrivalMain.getOrderDetailList();
            if(null == orderDetailList)throw new NuoNiuException("单据明细不能为空");
            Long mainId = purchaseArrivalMain.getId();
            UserInfo userInfo = UserThreadLocal.get();
            purchaseArrivalMain.setCompanyId(userInfo.getCompanyId());
            VPurchaseArrivalMain oldVPurchaseArrivalMain = null;
            Integer businessType = purchaseArrivalMain.getBusinessType();
//            if(null != businessType && (31 == businessType || 32 == businessType) && orderDetailList.stream().anyMatch(f->f.getBaseQuantity().compareTo(BigDecimal.ZERO) > 0)){
//                throw new NuoNiuException("单据明细错误：退货业务的明细数量不能为正数");
//            }
            if(mainId == null) {
                isNewMain = true;
                String code = getCodeForDelegate();
                if(code == null) {
                    throw new NuoNiuException("委外到货单编号已上限");
                }
                boolean isHaveId = orderDetailList.stream().anyMatch(f -> null != f.getId());
                if(isHaveId)throw new NuoNiuException("单据明细错误：不能新增已经存在的明细记录");
                purchaseArrivalMain.setDataSource("DelegateArrival");
                purchaseArrivalMain.setAccountId(erpAccountService.getCurrentAccountId());
                purchaseArrivalMain.setVoucherState(-1);
                purchaseArrivalMain.setVoucherCode(code);
                purchaseArrivalMain.setCompanyId(userInfo.getCompanyId());
                purchaseArrivalMain.setCreateUserId(userInfo.getUserId());
                purchaseArrivalMain.setClosedUserName(userInfo.getRealName());
                if (null == purchaseArrivalMain.getBusinessType()){
                    purchaseArrivalMain.setBusinessType(0);
                }
            }else {
                //校验详情（详情不能有其他单据的明细ID）
                boolean isHaveErrorId = orderDetailList.stream().anyMatch(f -> null != f.getOrderId() && !mainId.toString().equals(f.getOrderId().toString()));
                if(isHaveErrorId)throw new NuoNiuException("单据明细错误：不能修改其他单据的明细记录");
                purchaseArrivalMain.setUpdateUserId(userInfo.getUserId());
                purchaseArrivalMain.setUpdateDate(LocalDateTime.now());

                oldVPurchaseArrivalMain = getById(mainId);
                /**************  修改权限 *******************/
                if(!crmGoodsService.isHaveOperationRight(oldVPurchaseArrivalMain.getCreateUserId().longValue())){
                    throw new NuoNiuException("你没有权限操作该记录");
                }
                Integer voucherState = oldVPurchaseArrivalMain.getVoucherState();
                if(null != voucherState && voucherState > 0){
                    throw new NuoNiuException("已审核,不能修改");
                }
                purchaseArrivalMain.setAccountId(oldVPurchaseArrivalMain.getAccountId());
                purchaseArrivalMain.setSourceVoucherCode(oldVPurchaseArrivalMain.getSourceVoucherCode());
                purchaseArrivalMain.setSourceVoucherId(oldVPurchaseArrivalMain.getSourceVoucherId());
                purchaseArrivalMain.setSourceVoucherType(oldVPurchaseArrivalMain.getSourceVoucherType());
                purchaseArrivalMain.setSourceVoucherDate(oldVPurchaseArrivalMain.getSourceVoucherDate());
                //不可更新字段
                purchaseArrivalMain.setVoucherCode(null);
            }
            purchaseArrivalMain.setCumExecuteQuantity(null);
            purchaseArrivalMain.setCumRetQuantity(null);
            // 校验 明细数量
//            if(null != purchaseArrivalMain.getBusinessType() && (31 == purchaseArrivalMain.getBusinessType() || 32  == purchaseArrivalMain.getBusinessType())){
//                boolean isOk = purchaseArrivalMain.getOrderDetailList().stream().anyMatch(f -> null == f.getBaseQuantity() || !(f.getBaseQuantity().compareTo(BigDecimal.ZERO) < 0));
//                if(isOk)throw new NuoNiuException("明细数量必须小于0");
//            }else{
//                boolean isOk = purchaseArrivalMain.getOrderDetailList().stream().anyMatch(f -> null == f.getBaseQuantity() || !(f.getBaseQuantity().compareTo(BigDecimal.ZERO) > 0));
//                if(isOk)throw new NuoNiuException("明细数量必须大于0");
//            }
            boolean isOk = purchaseArrivalMain.getOrderDetailList().stream().anyMatch(f -> null == f.getBaseQuantity() || !(f.getBaseQuantity().compareTo(BigDecimal.ZERO) > 0));
            if(isOk)throw new NuoNiuException("明细数量必须大于0");
            //计算 明细物料 总数
            BigDecimal totalQuantity =  purchaseArrivalMain.getOrderDetailList().stream().map(VPurchaseArrivalDetail::getBaseQuantity).reduce(BigDecimal.ZERO,BigDecimal::add);
            purchaseArrivalMain.setTotalQuantity(totalQuantity.abs());

            Boolean result = this.saveOrUpdate(purchaseArrivalMain);
            if(result) {
                List<Long> detailIds = new ArrayList<>();
                orderDetailList.forEach(p -> {
                    p.setCompanyId(userInfo.getCompanyId());
                    p.setAccountId(purchaseArrivalMain.getAccountId());
                    p.setOrderId(purchaseArrivalMain.getId().intValue());
                    p.setSourceVoucherCode(purchaseArrivalMain.getSourceVoucherCode());
                    p.setSourceVoucherType(purchaseArrivalMain.getSourceVoucherType());
                    p.setSourceVoucherDate(purchaseArrivalMain.getSourceVoucherDate());
                    p.setSourceVoucherId(purchaseArrivalMain.getSourceVoucherId());
                    if(p.getId() != null) {
                        detailIds.add(p.getId());
                    }
                });
                boolean isDealDelete = false;
                if (null != mainId){
                    //删除明细
                    QueryWrapper wrapper = new QueryWrapper();
                    wrapper.eq("order_id", mainId);
                    if(detailIds != null && detailIds.size() > 0) {
                        wrapper.notIn("id", detailIds);
                    }
                    isDealDelete = arrivalDetailService.remove(wrapper);
                }
                //保存单据明细表
                arrivalDetailService.saveOrUpdateBatch(orderDetailList);
                // *** 如果 来源订单不为空,校验
                if( null != purchaseArrivalMain.getSourceVoucherId()){
                    if(isDealDelete)throw new NuoNiuException("有来源的单据不能删除明细");
                    if( !"DelegateProductionWork".equals(purchaseArrivalMain.getSourceVoucherType()) && !"DelegateArrival".equals(purchaseArrivalMain.getSourceVoucherType()))throw new NuoNiuException("委外到货单的来源单，只能是委外加工单或者委外到货单");
                    if( null != purchaseArrivalMain.getBusinessType() &&(32 == purchaseArrivalMain.getBusinessType() || 31 == purchaseArrivalMain.getBusinessType())&& !"DelegateArrival".equals(purchaseArrivalMain.getSourceVoucherType()))throw new NuoNiuException("退货流程的委外到货单的来源单，只能是委外到货单");
                    if( null != purchaseArrivalMain.getBusinessType() &&(32 != purchaseArrivalMain.getBusinessType()  && 31 != purchaseArrivalMain.getBusinessType())&& !"DelegateProductionWork".equals(purchaseArrivalMain.getSourceVoucherType()))throw new NuoNiuException("非退货流程的委外到货单的来源单，只能是委外加工单");
                    //1.是否是退货单且是普通退货流程
                    if( null != purchaseArrivalMain.getBusinessType() && 32 == purchaseArrivalMain.getBusinessType()){
                        VoucherMainRetBo voucherMainRetBo = new VoucherMainRetBo();
                        BeanUtils.copyProperties(purchaseArrivalMain,voucherMainRetBo);
                        List<VoucherDetailRetBo> voucherDetailRetBos = new ArrayList<>();
                        orderDetailList.forEach(detail->{
                            VoucherDetailRetBo voucherDetailRetBo = new VoucherDetailRetBo();
                            voucherDetailRetBos.add(voucherDetailRetBo);
                            BeanUtils.copyProperties(detail,voucherDetailRetBo);
                        });

                        VoucherSearchBo voucherSearchBo = new VoucherSearchBo();
                        voucherSearchBo.setSourceVoucherId(purchaseArrivalMain.getSourceVoucherId());
                        voucherSearchBo.setSourceVoucherType(purchaseArrivalMain.getSourceVoucherType());
                        voucherSearchBo.setVoucherId(purchaseArrivalMain.getId().intValue());
                        voucherSearchBo.setVoucherType("DelegateArrival");
                        //如果 是从 “退货冲抵” 到 “普通退货”，则先删除 冲抵执行情况，再做普通退货业务
                        if(null != oldVPurchaseArrivalMain && null != oldVPurchaseArrivalMain.getBusinessType() && oldVPurchaseArrivalMain.getBusinessType() == 31){
                            VoucherMainBo voucherMainBo = new VoucherMainBo();
                            BeanUtils.copyProperties(purchaseArrivalMain,voucherMainBo);
                            voucherMainBo.setBusinessType(31);   //对31做删除操作
                            List<VoucherDetailBo> voucherDetailBos = new ArrayList<>();
                            orderDetailList.forEach(detail->{
                                VoucherDetailBo voucherDetailBo = new VoucherDetailBo();
                                voucherDetailBos.add(voucherDetailBo);
                                BeanUtils.copyProperties(detail,voucherDetailBo);
                            });
                            voucherSearchBo.setCalculateType(2);
                            erpVoucherDesignService.calculateSourceVoucher(voucherMainBo,voucherDetailBos,voucherSearchBo);
                        }
                        voucherSearchBo.setCalculateType(1);

                        erpVoucherDesignService.calculateRetQuantity(voucherMainRetBo,voucherDetailRetBos,voucherSearchBo);
                    }else{

                        VoucherMainBo voucherMainBo = new VoucherMainBo();
                        BeanUtils.copyProperties(purchaseArrivalMain,voucherMainBo);
                        voucherMainBo.setIsNewMain(isNewMain);
                        List<VoucherDetailBo> voucherDetailBos = new ArrayList<>();
                        orderDetailList.forEach(detail->{
                            VoucherDetailBo voucherDetailBo = new VoucherDetailBo();
                            voucherDetailBos.add(voucherDetailBo);
                            BeanUtils.copyProperties(detail,voucherDetailBo);
                        });
                        VoucherSearchBo voucherSearchBo = new VoucherSearchBo();
                        voucherSearchBo.setSourceVoucherId(purchaseArrivalMain.getSourceVoucherId());
                        voucherSearchBo.setSourceVoucherType(purchaseArrivalMain.getSourceVoucherType());
                        voucherSearchBo.setVoucherId(purchaseArrivalMain.getId().intValue());
                        voucherSearchBo.setVoucherType("DelegateArrival");


                        //如果 是从 “普通退货” 到 “退货冲抵”，则先删除 普通退货 执行情况，再做普通退货业务
                        if(null != purchaseArrivalMain.getBusinessType() && 31 == purchaseArrivalMain.getBusinessType() && null != oldVPurchaseArrivalMain && null != oldVPurchaseArrivalMain.getBusinessType() && oldVPurchaseArrivalMain.getBusinessType() == 32){
                            VoucherMainRetBo voucherMainRetBo = new VoucherMainRetBo();
                            BeanUtils.copyProperties(purchaseArrivalMain,voucherMainRetBo);
                            voucherMainBo.setBusinessType(32);   //对32做删除操作
                            List<VoucherDetailRetBo> voucherDetailRetBos = new ArrayList<>();
                            orderDetailList.forEach(detail->{
                                VoucherDetailRetBo voucherDetailRetBo = new VoucherDetailRetBo();
                                voucherDetailRetBos.add(voucherDetailRetBo);
                                BeanUtils.copyProperties(detail,voucherDetailRetBo);
                            });
                            voucherSearchBo.setCalculateType(2);
                            erpVoucherDesignService.calculateRetQuantity(voucherMainRetBo,voucherDetailRetBos,voucherSearchBo);
                        }



                        voucherSearchBo.setCalculateType(1);
                        erpVoucherDesignService.calculateSourceVoucher(voucherMainBo,voucherDetailBos,voucherSearchBo);
                    }

                }
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteByIdForDelegate(Long id) {
        UserInfo userInfo = UserThreadLocal.get();
        VPurchaseArrivalMain purchaseArrivalMain = getById(id);

        if(purchaseArrivalMain == null) {
            throw new NuoNiuException("此单据不存在");
        }
        String dataSource = purchaseArrivalMain.getDataSource();
        /**************  修改权限 *******************/
        if(!crmGoodsService.isHaveOperationRight(purchaseArrivalMain.getCreateUserId().longValue())){
            throw new NuoNiuException("你没有权限操作该记录");
        }

        //如果 来源订单 不为空
        if(null != purchaseArrivalMain.getSourceVoucherId()){
            // 查询 当前单据明细
            List<VPurchaseArrivalDetail> orderDetails = arrivalDetailService.getOrderDetails(id);
            //1.是否是退货单且是普通退货流程
            if( null != purchaseArrivalMain.getBusinessType() &&32 == purchaseArrivalMain.getBusinessType() ){
                VoucherMainRetBo voucherMainRetBo = new VoucherMainRetBo();
                BeanUtils.copyProperties(purchaseArrivalMain,voucherMainRetBo);
                List<VoucherDetailRetBo> voucherDetailRetBos = new ArrayList<>();
                orderDetails.forEach(detail->{
                    VoucherDetailRetBo voucherDetailRetBo = new VoucherDetailRetBo();
                    voucherDetailRetBos.add(voucherDetailRetBo);
                    BeanUtils.copyProperties(detail,voucherDetailRetBo);
                });
                VoucherSearchBo voucherSearchBo = new VoucherSearchBo();
                voucherSearchBo.setCalculateType(2);
                voucherSearchBo.setSourceVoucherId(purchaseArrivalMain.getSourceVoucherId());
                voucherSearchBo.setSourceVoucherType(purchaseArrivalMain.getSourceVoucherType());
                voucherSearchBo.setVoucherId(purchaseArrivalMain.getId().intValue());
                voucherSearchBo.setVoucherType("DelegateArrival");
                erpVoucherDesignService.calculateRetQuantity(voucherMainRetBo,voucherDetailRetBos,voucherSearchBo);
            }else{

                VoucherMainBo voucherMainBo = new VoucherMainBo();
                BeanUtils.copyProperties(purchaseArrivalMain,voucherMainBo);
                List<VoucherDetailBo> voucherDetailBos = new ArrayList<>();
                orderDetails.forEach(detail->{
                    VoucherDetailBo voucherDetailBo = new VoucherDetailBo();
                    voucherDetailBos.add(voucherDetailBo);
                    BeanUtils.copyProperties(detail,voucherDetailBo);
                });
                VoucherSearchBo voucherSearchBo = new VoucherSearchBo();
                voucherSearchBo.setCalculateType(2);
                voucherSearchBo.setSourceVoucherId(purchaseArrivalMain.getSourceVoucherId());
                voucherSearchBo.setSourceVoucherType(purchaseArrivalMain.getSourceVoucherType());
                voucherSearchBo.setVoucherId(purchaseArrivalMain.getId().intValue());
                voucherSearchBo.setVoucherType("DelegateArrival");
                erpVoucherDesignService.calculateSourceVoucher(voucherMainBo,voucherDetailBos,voucherSearchBo);
            }
        }
        removeById(id);
        arrivalDetailService.removeByOrderId(id);
    }
}
